
#include "ThreadBase.h"


namespace cupid
{

ThreadBase::ThreadBase()
{
	m_thread		= NULL;
	m_closeThreadEvent	= NULL;
}


ThreadBase::~ThreadBase()
{
	if (m_thread) 
	{
		if (::WaitForSingleObject (m_thread, 0) == WAIT_TIMEOUT)
		{
			::TerminateThread (m_thread, 5);
			log("Hard terminate thread, may be lost some resources.");
		}

		::CloseHandle(m_thread);
	}

	if(m_closeThreadEvent)
		::CloseHandle(m_closeThreadEvent);
}

DWORD ThreadBase::threadProc ()
{
	DWORD	ret = 0;
	onInit();
	while(!isCloseEvent())
	{
		if(!onProcess())
		{
			ret = 2;
			break;
		}
		Sleep(1);
	}
	onDestroy();
	return ret;
}

bool ThreadBase::createThread (bool run)
{
	if (!isCreated ()) 
	{
		m_closeThreadEvent = ::CreateEvent(NULL, false, false, NULL);	
		if(m_closeThreadEvent == NULL)
		{
			log("Create close thread event failed.");
			return false;
		}

		DWORD	dwThreadID;		
		DWORD	dwCreationFlags = run ? 0 : CREATE_SUSPENDED;
		m_thread = ::CreateThread (NULL, 0, (DWORD (WINAPI *)(LPVOID))trueThreadProc, 
									(void *)(ThreadBase *)this, dwCreationFlags, &dwThreadID);
		if(m_thread)
		{
			return true;
		}
		else
		{
			::CloseHandle(m_closeThreadEvent);
			log("Create thread failed.");
			return false;
		}
	}
	else
	{
		log("Can't create thread since already created.");
		return false;
	}
}

bool ThreadBase::resumeThread()	
{
	if(m_thread) 
	{
		if(::ResumeThread(m_thread) != -1)
			return true;
	}
	else
	{
		int err = GetLastError();
		log("::ResumeThread() failed[%d] in ResumeThread().", err);
	}

	return false;
}


bool ThreadBase::closeThread(long msec )
{
	if(m_thread)
	{
		::ResumeThread(m_thread);			
		::SetEvent(m_closeThreadEvent);
		if(::WaitForSingleObject(m_thread, msec) != WAIT_TIMEOUT)	
		{
			::CloseHandle(m_thread);
			m_thread = NULL;
			::CloseHandle(m_closeThreadEvent);
			m_closeThreadEvent = NULL;
		}
		else
		{
			return false;
		}
	}

	return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////
bool ThreadBase::isCloseEvent(long msec /*= 0*/)	
{
	if(::WaitForSingleObject(m_closeThreadEvent, msec) != WAIT_TIMEOUT)
		return true;
	else
		return false;
}


//*********************************************************
//creates the thread
//*********************************************************
DWORD WINAPI ThreadBase::trueThreadProc(LPVOID param)
{
	ThreadBase *	thr;
	thr			= (ThreadBase*)param;
	return thr->threadProc();
}

}